﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Web.HttpUtility;

namespace WebGetter
{
    public class Page : BaseEntity
    {
        public string Url { get; set; }
        public string Author { get; set; }
        public string Title { get; set; }
        public int PageNo { get; set; }
        public int TotalNo { get; set; }
        public List<Reply> Replies { get; private set; }
        public string NextPageUrl { get; private set; }
        public List<VisitLog> VistLogs { get; set; }


        List<string> needVerifyProperty = new List<string> { Keys.Author, Keys.Content,/* Keys.Floor,*/ Keys.PostTime };

        public Page()
        {
            VistLogs = new List<VisitLog>();
            Replies = new List<Reply>();
        }

        public Page(string url, string nextUrl, RegexHelper helper)
            : this()
        {
            Parse(helper);
        }

        public Page(string url, RegexHelper helper)
            : this()
        {
            this.Url = url;
            Parse(helper);
        }

        public Page(RegexHelper helper)
            : this()
        {
            Parse(helper);
        }

        public static Page GetPage(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                return null;
            }

            string content = HttpUtility.GetHtml(url);
            RegexHelper helper = new RegexHelper(content);
            helper.DicData = new Dictionary<string, List<string>>();
            return ExecuteRule(url, content, helper);
        }

        private static Page ExecuteRule(string url, string content, RegexHelper helper)
        {
            IWebGetRule rule = RuleFactory.GetRule(url);
            rule.InitHelper(helper);
            string newUrl = rule.GetCurrentUrl(helper);
            if (!string.IsNullOrEmpty(newUrl))
            {
                url = UrlHelper.GetFullUrlWithBaseUrl(newUrl, url);
            }
            return new Page(url, helper);
        }

        public void Parse(RegexHelper helper)
        {
            string nextUrl = helper.GetKeyItem(Keys.NextUrl);
            Author = helper.GetKeyItem(Keys.PageAuthor);
            Title = helper.GetKeyItem(Keys.Title);
            PageNo = GetInt(helper.GetKeyItem(Keys.PageNo));
            TotalNo = GetInt(helper.GetKeyItem(Keys.TotalNo));
            if (TotalNo == 0)
                TotalNo = PageNo;
            if (!string.IsNullOrEmpty(Url))
            {
                NextPageUrl = UrlHelper.GetFullUrlWithBaseUrl(nextUrl, Url);
            }

            if (VarifyData(helper.DicData))
            {
                for (int i = 0; i < GetRepliesCount(helper.DicData); i++)
                {
                    Reply reply = new Reply
                    {
                        Author = helper.DicData[Keys.Author][i],
                        PostTime = GetDataTime(helper.DicData[Keys.PostTime][i]),
                        Content = helper.DicData[Keys.Content][i]
                    };

                    if (needVerifyProperty.Contains(Keys.Floor))
                        reply.Floor = helper.DicData[Keys.Floor][i];
                    Replies.Add(reply);
                }
            }
        }

        private DateTime GetDataTime(string s)
        {
            DateTime dt;
            if (!DateTime.TryParse(s, out dt))
            {
                if (!DateTime.TryParse(s.Trim() + " 00:00:00", out dt))
                {
                    dt = DateTime.MinValue;
                }
            }
            return dt;
        }

        private int GetInt(string s, int defaultValue = 0)
        {
            int.TryParse(s, out defaultValue);
            return defaultValue;
        }

        private int GetRepliesCount(Dictionary<string, List<string>> dicData)
        {
            foreach (var item in dicData)
            {
                if (needVerifyProperty.Contains(item.Key))
                    return item.Value.Count;
            }
            return 0;
        }

        private bool VarifyData(Dictionary<string, List<string>> dicData)
        {
            int count = 0;
            foreach (var item in dicData)
            {
                if (!needVerifyProperty.Contains(item.Key))
                {
                    continue;
                }
                if (item.Value.Count == 0)
                {
                    return false;
                }
                if (count == 0)
                {
                    count = item.Value.Count;
                    continue;
                }
                if ((item.Value.Count != count))
                {
                    return false;
                }
            }
            return true;
        }
    }
}
